home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / POLYGON.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-01  |  22.0 KB  |  1,092 lines

  1. /****************************************************************************
  2. *                   polygon.c
  3. *
  4. *  This module implements functions that manipulate polygons.
  5. *
  6. *  This module was written by Dieter Bayer [DB].
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. /****************************************************************************
  27. *
  28. *  Explanation:
  29. *
  30. *  Syntax:
  31. *
  32. *  ---
  33. *
  34. *  The "inside polygon"-test was taken from:
  35. *
  36. *    E. Haines, "An Introduction to Ray-Tracing", ..., pp. 53-59
  37. *
  38. *  ---
  39. *
  40. *  May 1994 : Creation. [DB]
  41. *
  42. *  Oct 1994 : Changed polygon structure. Polygon points are now stored
  43. *             in a seperate structure. This - together with the use of
  44. *             a transformation - allows to keep just one point definition
  45. *             for multiple copies of one polygon. [DB]
  46. *
  47. *****************************************************************************/
  48.  
  49. #include "frame.h"
  50. #include "vector.h"
  51. #include "povproto.h"
  52. #include "matrices.h"
  53. #include "objects.h"
  54. #include "polygon.h"
  55. #include "povray.h"
  56.  
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Local preprocessor defines
  62. ******************************************************************************/
  63.  
  64. /* Minimal intersection depth for a valid intersection. */
  65.  
  66. #define DEPTH_TOLERANCE 1.0e-8
  67.  
  68. /* If |x| < ZERO_TOLERANCE x is assumed to be 0. */
  69.  
  70. #define ZERO_TOLERANCE 1.0e-10
  71.  
  72.  
  73.  
  74.  
  75. /*****************************************************************************
  76. * Static functions
  77. ******************************************************************************/
  78.  
  79. static int intersect_poylgon PARAMS((RAY *Ray, POLYGON *Polyg, DBL *Depth));
  80. static int in_polygon PARAMS((int Number, UV_VECT *Points, DBL u, DBL v));
  81. static int  All_Polygon_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  82. static int  Inside_Polygon PARAMS((VECTOR point, OBJECT *Object));
  83. static void Polygon_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
  84. static void *Copy_Polygon PARAMS((OBJECT *Object));
  85. static void Translate_Polygon PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  86. static void Rotate_Polygon PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  87. static void Scale_Polygon PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  88. static void Transform_Polygon PARAMS((OBJECT *Object, TRANSFORM *Trans));
  89. static void Invert_Polygon PARAMS((OBJECT *Object));
  90. static void Destroy_Polygon PARAMS((OBJECT *Object));
  91. static void Compute_Polygon_BBox PARAMS((POLYGON *Polyg));
  92.  
  93.  
  94.  
  95. /*****************************************************************************
  96. * Local variables
  97. ******************************************************************************/
  98.  
  99. static METHODS Polygon_Methods =
  100. {
  101.   All_Polygon_Intersections,
  102.   Inside_Polygon, Polygon_Normal,
  103.   Copy_Polygon,
  104.   Translate_Polygon, Rotate_Polygon,
  105.   Scale_Polygon, Transform_Polygon, Invert_Polygon, Destroy_Polygon
  106. };
  107.  
  108.  
  109.  
  110. /*****************************************************************************
  111. *
  112. * FUNCTION
  113. *
  114. *   All_Polygon_Intersections
  115. *
  116. * INPUT
  117. *
  118. *   Object      - Object
  119. *   Ray         - Ray
  120. *   Depth_Stack - Intersection stack
  121. *   
  122. * OUTPUT
  123. *
  124. *   Depth_Stack
  125. *   
  126. * RETURNS
  127. *
  128. *   int - TRUE, if a intersection was found
  129. *   
  130. * AUTHOR
  131. *
  132. *   Dieter Bayer
  133. *   
  134. * DESCRIPTION
  135. *
  136. *   Determine ray/polygon intersection and clip intersection found.
  137. *
  138. * CHANGES
  139. *
  140. *   May 1994 : Creation.
  141. *
  142. ******************************************************************************/
  143.  
  144. static int All_Polygon_Intersections(Object, Ray, Depth_Stack)
  145. OBJECT *Object;
  146. RAY *Ray;
  147. ISTACK *Depth_Stack;
  148. {
  149.   DBL Depth;
  150.   VECTOR IPoint;
  151.  
  152.   if (intersect_poylgon(Ray, (POLYGON *)Object, &Depth))
  153.   {
  154.     VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
  155.  
  156.     if (Point_In_Clip(IPoint, Object->Clip))
  157.     {
  158.       push_entry(Depth, IPoint, Object, Depth_Stack);
  159.  
  160.       return(TRUE);
  161.     }
  162.   }
  163.  
  164.   return(FALSE);
  165. }
  166.  
  167.  
  168.  
  169. /*****************************************************************************
  170. *
  171. * FUNCTION
  172. *
  173. *   intersect_poylgon
  174. *
  175. * INPUT
  176. *
  177. *   Ray     - Ray
  178. *   Polyg - Polygon
  179. *   Depth   - Depth of intersection found
  180. *   
  181. * OUTPUT
  182. *
  183. *   Depth
  184. *   
  185. * RETURNS
  186. *
  187. *   int - TRUE if intersection found
  188. *   
  189. * AUTHOR
  190. *
  191. *   Dieter Bayer
  192. *   
  193. * DESCRIPTION
  194. *
  195. *   Determine ray/polygon intersection.
  196. *
  197. * CHANGES
  198. *
  199. *   May 1994 : Creation.
  200. *
  201. ******************************************************************************/
  202.  
  203. static int intersect_poylgon(Ray, Polyg, Depth)
  204. RAY *Ray;
  205. POLYGON *Polyg;
  206. DBL *Depth;
  207. {
  208.   DBL x, y, len;
  209.   VECTOR p, d;
  210.  
  211.   /* Don't test degenerate polygons. */
  212.  
  213.   if (Test_Flag(Polyg, DEGENERATE_FLAG))
  214.   {
  215.     return(FALSE);
  216.   }
  217.  
  218.   Increase_Counter(stats[Ray_Polygon_Tests]);
  219.  
  220.   /* Transform the ray into the polygon space. */
  221.  
  222.   MInvTransPoint(p, Ray->Initial, Polyg->Trans);
  223.  
  224.   MInvTransDirection(d, Ray->Direction, Polyg->Trans);
  225.  
  226.   VLength(len, d);
  227.  
  228.   VInverseScaleEq(d, len);
  229.  
  230.   /* Intersect ray with the plane in which the polygon lies. */
  231.  
  232.   if (fabs(d[Z]) < ZERO_TOLERANCE)
  233.   {
  234.     return(FALSE);
  235.   }
  236.  
  237.   *Depth = -p[Z] / d[Z];
  238.  
  239.   if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance))
  240.   {
  241.     return(FALSE);
  242.   }
  243.  
  244.   /* Does the intersection point lie inside the polygon? */
  245.  
  246.   x = p[X] + *Depth * d[X];
  247.   y = p[Y] + *Depth * d[Y];
  248.  
  249.   if (in_polygon(Polyg->Data->Number, Polyg->Data->Points, x, y))
  250.   {
  251.     Increase_Counter(stats[Ray_Polygon_Tests_Succeeded]);
  252.  
  253.     *Depth /= len;
  254.  
  255.     return (TRUE);
  256.   }
  257.   else
  258.   {
  259.     return (FALSE);
  260.   }
  261. }
  262.  
  263.  
  264.  
  265. /*****************************************************************************
  266. *
  267. * FUNCTION
  268. *
  269. *   Inside_Polygon
  270. *
  271. * INPUT
  272. *
  273. *   IPoint - Intersection point
  274. *   Object - Object
  275. *   
  276. * OUTPUT
  277. *   
  278. * RETURNS
  279. *
  280. *   int - always FALSE
  281. *   
  282. * AUTHOR
  283. *
  284. *   Dieter Bayer
  285. *   
  286. * DESCRIPTION
  287. *
  288. *   Polygons can't be used in CSG.
  289. *
  290. * CHANGES
  291. *
  292. *   May 1994 : Creation.
  293. *
  294. ******************************************************************************/
  295.  
  296. static int Inside_Polygon(IPoint, Object)
  297. VECTOR IPoint;
  298. OBJECT *Object;
  299. {
  300.   return(FALSE);
  301. }
  302.  
  303.  
  304.  
  305. /*****************************************************************************
  306. *
  307. * FUNCTION
  308. *
  309. *   Polygon_Normal
  310. *
  311. * INPUT
  312. *
  313. *   Result - Normal vector
  314. *   Object - Object
  315. *   Inter  - Intersection found
  316. *   
  317. * OUTPUT
  318. *
  319. *   Result
  320. *   
  321. * RETURNS
  322. *   
  323. * AUTHOR
  324. *
  325. *   Dieter Bayer
  326. *   
  327. * DESCRIPTION
  328. *
  329. *   Calculate the normal of the polygon in a given point.
  330. *
  331. * CHANGES
  332. *
  333. *   May 1994 : Creation.
  334. *
  335. ******************************************************************************/
  336.  
  337. static void Polygon_Normal(Result, Object, Inter)
  338. OBJECT *Object;
  339. VECTOR Result;
  340. INTERSECTION *Inter;
  341. {
  342.   Assign_Vector(Result, ((POLYGON *)Object)->S_Normal);
  343. }
  344.  
  345.  
  346.  
  347. /*****************************************************************************
  348. *
  349. * FUNCTION
  350. *
  351. *   Translate_Polygon
  352. *
  353. * INPUT
  354. *
  355. *   Object - Object
  356. *   Vector - Translation vector
  357. *   
  358. * OUTPUT
  359. *
  360. *   Object
  361. *   
  362. * RETURNS
  363. *   
  364. * AUTHOR
  365. *
  366. *   Dieter Bayer
  367. *   
  368. * DESCRIPTION
  369. *
  370. *   Translate a polygon.
  371. *
  372. * CHANGES
  373. *
  374. *   May 1994 : Creation.
  375. *
  376. ******************************************************************************/
  377.  
  378. static void Translate_Polygon(Object, Vector, Trans)
  379. OBJECT *Object;
  380. VECTOR Vector;
  381. TRANSFORM *Trans;
  382. {
  383.   Transform_Polygon(Object, Trans);
  384. }
  385.  
  386.  
  387.  
  388. /*****************************************************************************
  389. *
  390. * FUNCTION
  391. *
  392. *   Rotate_Polygon
  393. *
  394. * INPUT
  395. *
  396. *   Object - Object
  397. *   Vector - Rotation vector
  398. *   
  399. * OUTPUT
  400. *
  401. *   Object
  402. *   
  403. * RETURNS
  404. *   
  405. * AUTHOR
  406. *
  407. *   Dieter Bayer
  408. *   
  409. * DESCRIPTION
  410. *
  411. *   Rotate a polygon.
  412. *
  413. * CHANGES
  414. *
  415. *   May 1994 : Creation.
  416. *
  417. ******************************************************************************/
  418.  
  419. static void Rotate_Polygon(Object, Vector, Trans)
  420. OBJECT *Object;
  421. VECTOR Vector;
  422. TRANSFORM *Trans;
  423. {
  424.   Transform_Polygon(Object, Trans);
  425. }
  426.  
  427.  
  428.  
  429. /*****************************************************************************
  430. *
  431. * FUNCTION
  432. *
  433. *   Scale_Polygon
  434. *
  435. * INPUT
  436. *
  437. *   Object - Object
  438. *   Vector - Scaling vector
  439. *   
  440. * OUTPUT
  441. *
  442. *   Object
  443. *   
  444. * RETURNS
  445. *   
  446. * AUTHOR
  447. *
  448. *   Dieter Bayer
  449. *   
  450. * DESCRIPTION
  451. *
  452. *   Scale a polygon.
  453. *
  454. * CHANGES
  455. *
  456. *   May 1994 : Creation.
  457. *
  458. ******************************************************************************/
  459.  
  460. static void Scale_Polygon(Object, Vector, Trans)
  461. OBJECT *Object;
  462. VECTOR Vector;
  463. TRANSFORM *Trans;
  464. {
  465.   Transform_Polygon(Object, Trans);
  466. }
  467.  
  468.  
  469.  
  470. /*****************************************************************************
  471. *
  472. * FUNCTION
  473. *
  474. *   Transform_Polygon
  475. *
  476. * INPUT
  477. *
  478. *   Object - Object
  479. *   Trans  - Transformation to apply
  480. *   
  481. * OUTPUT
  482. *
  483. *   Object
  484. *   
  485. * RETURNS
  486. *   
  487. * AUTHOR
  488. *
  489. *   Dieter Bayer
  490. *   
  491. * DESCRIPTION
  492. *
  493. *   Transform a polygon by transforming all points
  494. *   and recalculating the polygon.
  495. *
  496. * CHANGES
  497. *
  498. *   May 1994 : Creation.
  499. *
  500. ******************************************************************************/
  501.  
  502. static void Transform_Polygon(Object, Trans)
  503. OBJECT *Object;
  504. TRANSFORM *Trans;
  505. {
  506.   VECTOR N;
  507.   POLYGON *Polyg = (POLYGON *)Object;
  508.  
  509.   Compose_Transforms(Polyg->Trans, Trans);
  510.  
  511.   Make_Vector(N, 0.0, 0.0, 1.0);
  512.   MTransNormal(Polyg->S_Normal, N, Polyg->Trans);
  513.  
  514.   VNormalizeEq(Polyg->S_Normal);
  515.  
  516.   Compute_Polygon_BBox(Polyg);
  517. }
  518.  
  519.  
  520.  
  521. /*****************************************************************************
  522. *
  523. * FUNCTION
  524. *
  525. *   Invert_Polygon
  526. *
  527. * INPUT
  528. *
  529. *   Object - Object
  530. *   
  531. * OUTPUT
  532. *
  533. *   Object
  534. *   
  535. * RETURNS
  536. *   
  537. * AUTHOR
  538. *
  539. *   Dieter Bayer
  540. *   
  541. * DESCRIPTION
  542. *
  543. *   Invert a polygon.
  544. *
  545. * CHANGES
  546. *
  547. *   May 1994 : Creation.
  548. *
  549. ******************************************************************************/
  550.  
  551. static void Invert_Polygon(Object)
  552. OBJECT *Object;
  553. {
  554. }
  555.  
  556.  
  557.  
  558. /*****************************************************************************
  559. *
  560. * FUNCTION
  561. *
  562. *   Create_Polygon
  563. *
  564. * INPUT
  565. *   
  566. * OUTPUT
  567. *   
  568. * RETURNS
  569. *
  570. *   POLYGON * - new polygon
  571. *   
  572. * AUTHOR
  573. *
  574. *   Dieter Bayer
  575. *   
  576. * DESCRIPTION
  577. *
  578. *   Create a new polygon.
  579. *
  580. * CHANGES
  581. *
  582. *   May 1994 : Creation.
  583. *
  584. ******************************************************************************/
  585.  
  586. POLYGON *Create_Polygon()
  587. {
  588.   POLYGON *New;
  589.  
  590.   New = (POLYGON *)POV_MALLOC(sizeof(POLYGON), "polygon");
  591.  
  592.   INIT_OBJECT_FIELDS(New,POLYGON_OBJECT,&Polygon_Methods)
  593.  
  594.   New->Trans = Create_Transform();
  595.  
  596.   Make_Vector(New->S_Normal, 0.0, 0.0, 1.0);
  597.  
  598.   New->Data = NULL;
  599.  
  600.   return (New);
  601. }
  602.  
  603.  
  604.  
  605. /*****************************************************************************
  606. *
  607. * FUNCTION
  608. *
  609. *   Copy_Polygon
  610. *
  611. * INPUT
  612. *
  613. *   Object - Object
  614. *   
  615. * OUTPUT
  616. *   
  617. * RETURNS
  618. *
  619. *   void * - New polygon
  620. *   
  621. * AUTHOR
  622. *
  623. *   Dieter Bayer
  624. *   
  625. * DESCRIPTION
  626. *
  627. *   Copy a polygon structure.
  628. *
  629. * CHANGES
  630. *
  631. *   May 1994 : Creation.
  632. *
  633. ******************************************************************************/
  634.  
  635. static void *Copy_Polygon(Object)
  636. OBJECT *Object;
  637. {
  638.   POLYGON *New, *Polyg = (POLYGON *)Object;
  639.  
  640.   New = Create_Polygon ();
  641.  
  642.   /* Get rid of the transformation created in Create_Polygon(). */
  643.  
  644.   Destroy_Transform(New->Trans);
  645.  
  646.   /* Copy polygon. */
  647.  
  648.   *New = *Polyg;
  649.  
  650.   New->Trans = Copy_Transform(Polyg->Trans);
  651.  
  652.   New->Data->References++;
  653.  
  654.   return (New);
  655. }
  656.  
  657.  
  658.  
  659. /*****************************************************************************
  660. *
  661. * FUNCTION
  662. *
  663. *   Destroy_Polygon
  664. *
  665. * INPUT
  666. *
  667. *   Object - Object
  668. *   
  669. * OUTPUT
  670. *
  671. *   Object
  672. *   
  673. * RETURNS
  674. *   
  675. * AUTHOR
  676. *
  677. *   Dieter Bayer
  678. *   
  679. * DESCRIPTION
  680. *
  681. *   Destroy a polygon.
  682. *
  683. * CHANGES
  684. *
  685. *   May 1994 : Creation.
  686. *
  687. *   Dec 1994 : Fixed memory leakage. [DB]
  688. *
  689. ******************************************************************************/
  690.  
  691. static void Destroy_Polygon(Object)
  692. OBJECT *Object;
  693. {
  694.   POLYGON *Polyg = (POLYGON *)Object;
  695.  
  696.   if (--(Polyg->Data->References) == 0)
  697.   {
  698.     POV_FREE (Polyg->Data->Points);
  699.  
  700.     POV_FREE (Polyg->Data);
  701.   }
  702.  
  703.   Destroy_Transform(Polyg->Trans);
  704.  
  705.   POV_FREE (Object);
  706. }
  707.  
  708.  
  709.  
  710. /*****************************************************************************
  711. *
  712. * FUNCTION
  713. *
  714. *   Compute_Polygon
  715. *
  716. * INPUT
  717. *
  718. *   Polyg - Polygon
  719. *   Points  - 3D points describing the polygon
  720. *   
  721. * OUTPUT
  722. *
  723. *   Polyg
  724. *   
  725. * RETURNS
  726. *   
  727. * AUTHOR
  728. *
  729. *   Dieter Bayer
  730. *   
  731. * DESCRIPTION
  732. *
  733. *   Compute the following things for a given polygon:
  734. *
  735. *     - Polygon transformation
  736. *
  737. *     - Array of 2d points describing the shape of the polygon
  738. *
  739. * CHANGES
  740. *
  741. *   May 1994 : Creation.
  742. *
  743. ******************************************************************************/
  744.  
  745. void Compute_Polygon(Polyg, Number, Points)
  746. POLYGON *Polyg;
  747. int Number;
  748. VECTOR *Points;
  749. {
  750.   int i;
  751.   DBL x, y, z, d;
  752.   VECTOR o, u, v, w, N;
  753.   MATRIX a, b;
  754.  
  755.   /* Create polygon data. */
  756.  
  757.   if (Polyg->Data == NULL)
  758.   {
  759.     Polyg->Data = (POLYGON_DATA *)POV_MALLOC(sizeof(POLYGON_DATA), "polygon points");
  760.  
  761.     Polyg->Data->References = 1;
  762.  
  763.     Polyg->Data->Number = Number;
  764.  
  765.     Polyg->Data->Points = (UV_VECT *)POV_MALLOC(Number*sizeof(UV_VECT), "polygon points");
  766.   }
  767.   else
  768.   {
  769.     Error("Polygon data already computed.");
  770.   }
  771.  
  772.   /* Get polygon's coordinate system (one of the many possible) */
  773.  
  774.   Assign_Vector(o, Points[0]);
  775.  
  776.   /* Find valid, i.e. non-zero u vector. */
  777.   
  778.   for (i = 1; i < Number; i++)
  779.   {
  780.     VSub(u, Points[i], o);
  781.  
  782.     if (VSumSqr(u) > EPSILON)
  783.     {
  784.       break;
  785.     }
  786.   }
  787.  
  788.   if (i == Number)
  789.   {
  790.     Set_Flag(Polyg, DEGENERATE_FLAG);
  791.  
  792.     Warning(0.0, "Points in polygon are co-linear. Ignoring polygon.\n");
  793.   }
  794.  
  795.   /* Find valid, i.e. non-zero v and w vectors. */
  796.   
  797.   for (i++; i < Number; i++)
  798.   {
  799.     VSub(v, Points[i], o);
  800.     
  801.     VCross(w, u, v);
  802.  
  803.     if ((VSumSqr(v) > EPSILON) && (VSumSqr(w) > EPSILON))
  804.     {
  805.       break;
  806.     }
  807.   }
  808.  
  809.   if (i == Number)
  810.   {
  811.     Set_Flag(Polyg, DEGENERATE_FLAG);
  812.  
  813.     Warning(0.0, "Points in polygon are co-linear. Ignoring polygon.\n");
  814.   }
  815.  
  816.   VCross(u, v, w);
  817.   VCross(v, w, u);
  818.  
  819.   VNormalize(u, u);
  820.   VNormalize(v, v);
  821.   VNormalize(w, w);
  822.  
  823.   MIdentity(a);
  824.   MIdentity(b);
  825.  
  826.   a[3][0] = -o[X];
  827.   a[3][1] = -o[Y];
  828.   a[3][2] = -o[Z];
  829.  
  830.   b[0][0] =  u[X];
  831.   b[1][0] =  u[Y];
  832.   b[2][0] =  u[Z];
  833.  
  834.   b[0][1] =  v[X];
  835.   b[1][1] =  v[Y];
  836.   b[2][1] =  v[Z];
  837.  
  838.   b[0][2] =  w[X];
  839.   b[1][2] =  w[Y];
  840.   b[2][2] =  w[Z];
  841.  
  842.   MTimes(Polyg->Trans->inverse, a, b);
  843.  
  844.   MInvers(Polyg->Trans->matrix, Polyg->Trans->inverse);
  845.  
  846.   /* Project points onto the u,v-plane (3D --> 2D) */
  847.  
  848.   for (i = 0; i < Number; i++)
  849.   {
  850.     x = Points[i][X] - o[X];
  851.     y = Points[i][Y] - o[Y];
  852.     z = Points[i][Z] - o[Z];
  853.  
  854.     d = x * w[X] + y * w[Y] + z * w[Z];
  855.  
  856.     if (fabs(d) > ZERO_TOLERANCE)
  857.     {
  858.       Set_Flag(Polyg, DEGENERATE_FLAG);
  859.  
  860.       Warning(0.0, "Points in polygon are not co-planar. Ignoring polygons.\n");
  861.     }
  862.  
  863.     Polyg->Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z];
  864.     Polyg->Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z];
  865.   }
  866.   
  867.   Make_Vector(N, 0.0, 0.0, 1.0);
  868.   MTransNormal(Polyg->S_Normal, N, Polyg->Trans);
  869.  
  870.   VNormalizeEq(Polyg->S_Normal);
  871.  
  872.   Compute_Polygon_BBox(Polyg);
  873. }
  874.  
  875.  
  876.  
  877. /*****************************************************************************
  878. *
  879. * FUNCTION
  880. *
  881. *   Compute_Polygon_BBox
  882. *
  883. * INPUT
  884. *
  885. *   Polyg - Polygon
  886. *   
  887. * OUTPUT
  888. *
  889. *   Polyg
  890. *   
  891. * RETURNS
  892. *   
  893. * AUTHOR
  894. *
  895. *   Dieter Bayer
  896. *   
  897. * DESCRIPTION
  898. *
  899. *   Calculate the bounding box of a polygon.
  900. *
  901. * CHANGES
  902. *
  903. *   May 1994 : Creation.
  904. *
  905. ******************************************************************************/
  906.  
  907. static void Compute_Polygon_BBox(Polyg)
  908. POLYGON *Polyg;
  909. {
  910.   int i;
  911.   VECTOR p, Puv, Min, Max;
  912.  
  913.   Min[X] = Min[Y] = Min[Z] =  BOUND_HUGE;
  914.   Max[X] = Max[Y] = Max[Z] = -BOUND_HUGE;
  915.  
  916.   for (i = 0; i < Polyg->Data->Number; i++)
  917.   {
  918.     Puv[X] = Polyg->Data->Points[i][X];
  919.     Puv[Y] = Polyg->Data->Points[i][Y];
  920.     Puv[Z] = 0.0;
  921.  
  922.     MTransPoint(p, Puv, Polyg->Trans);
  923.  
  924.     Min[X] = min(Min[X], p[X]);
  925.     Min[Y] = min(Min[Y], p[Y]);
  926.     Min[Z] = min(Min[Z], p[Z]);
  927.     Max[X] = max(Max[X], p[X]);
  928.     Max[Y] = max(Max[Y], p[Y]);
  929.     Max[Z] = max(Max[Z], p[Z]);
  930.   }
  931.  
  932.   Make_BBox_from_min_max(Polyg->BBox, Min, Max);
  933.  
  934.   if (fabs(Polyg->BBox.Lengths[X]) < Small_Tolerance)
  935.   {
  936.     Polyg->BBox.Lower_Left[X] -= Small_Tolerance;
  937.     Polyg->BBox.Lengths[X]    += 2.0 * Small_Tolerance;
  938.   }
  939.  
  940.   if (fabs(Polyg->BBox.Lengths[Y]) < Small_Tolerance)
  941.   {
  942.     Polyg->BBox.Lower_Left[Y] -= Small_Tolerance;
  943.     Polyg->BBox.Lengths[Y]    += 2.0 * Small_Tolerance;
  944.   }
  945.  
  946.   if (fabs(Polyg->BBox.Lengths[Z]) < Small_Tolerance)
  947.   {
  948.     Polyg->BBox.Lower_Left[Z] -= Small_Tolerance;
  949.     Polyg->BBox.Lengths[Z]    += 2.0 * Small_Tolerance;
  950.   }
  951. }
  952.  
  953.  
  954.  
  955. /*****************************************************************************
  956. *
  957. * FUNCTION
  958. *
  959. *   in_polygon
  960. *
  961. * INPUT
  962. *
  963. *   Number - Number of points
  964. *   Points - Points describing polygon's shape
  965. *   u, v   - 2D-coordinates of the point to test
  966. *   
  967. * OUTPUT
  968. *   
  969. * RETURNS
  970. *
  971. *   int - TRUE, if inside
  972. *   
  973. * AUTHOR
  974. *
  975. *   Eric Haines, 3D/Eye Inc, erich@eye.com
  976. *   
  977. * DESCRIPTION
  978. *
  979. * ======= Crossings Multiply algorithm ===================================
  980. *
  981. * This version is usually somewhat faster than the original published in
  982. * Graphics Gems IV; by turning the division for testing the X axis crossing
  983. * into a tricky multiplication test this part of the test became faster,
  984. * which had the additional effect of making the test for "both to left or
  985. * both to right" a bit slower for triangles than simply computing the
  986. * intersection each time.  The main increase is in triangle testing speed,
  987. * which was about 15% faster; all other polygon complexities were pretty much
  988. * the same as before.  On machines where division is very expensive (not the
  989. * case on the HP 9000 series on which I tested) this test should be much
  990. * faster overall than the old code.  Your mileage may (in fact, will) vary,
  991. * depending on the machine and the test data, but in general I believe this
  992. * code is both shorter and faster.  This test was inspired by unpublished
  993. * Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
  994. * Related work by Samosky is in:
  995. *
  996. * Samosky, Joseph, "SectionView: A system for interactively specifying and
  997. * visualizing sections through three-dimensional medical image data",
  998. * M.S. Thesis, Department of Electrical Engineering and Computer Science,
  999. * Massachusetts Institute of Technology, 1993.
  1000. *
  1001. *
  1002. * Shoot a test ray along +X axis.  The strategy is to compare vertex Y values
  1003. * to the testing point's Y and quickly discard edges which are entirely to one
  1004. * side of the test ray.
  1005. *
  1006. * CHANGES
  1007. *
  1008. *   -
  1009. *
  1010. ******************************************************************************/
  1011.  
  1012. static int in_polygon(Number, Points, u, v)
  1013. int Number;
  1014. UV_VECT *Points;
  1015. DBL u, v;
  1016. {
  1017.   register int i, yflag0, yflag1, inside_flag;
  1018.   register DBL ty, tx;
  1019.   register DBL *vtx0, *vtx1, *first;
  1020.  
  1021.   tx = u;
  1022.   ty = v;
  1023.  
  1024.   vtx0 = &Points[0][X];
  1025.   vtx1 = &Points[1][X];
  1026.  
  1027.   first = vtx0;
  1028.  
  1029.   /* get test bit for above/below X axis */
  1030.  
  1031.   yflag0 = (vtx0[Y] >= ty);
  1032.  
  1033.   inside_flag = FALSE;
  1034.  
  1035.   for (i = 1; i < Number; )
  1036.   {
  1037.     yflag1 = (vtx1[Y] >= ty);
  1038.  
  1039.     /*
  1040.      * Check if endpoints straddle (are on opposite sides) of X axis
  1041.      * (i.e. the Y's differ); if so, +X ray could intersect this edge.
  1042.      * The old test also checked whether the endpoints are both to the
  1043.      * right or to the left of the test point.  However, given the faster
  1044.      * intersection point computation used below, this test was found to
  1045.      * be a break-even proposition for most polygons and a loser for
  1046.      * triangles (where 50% or more of the edges which survive this test
  1047.      * will cross quadrants and so have to have the X intersection computed
  1048.      * anyway).  I credit Joseph Samosky with inspiring me to try dropping
  1049.      * the "both left or both right" part of my code.
  1050.      */
  1051.  
  1052.     if (yflag0 != yflag1)
  1053.     {
  1054.       /*
  1055.        * Check intersection of pgon segment with +X ray.
  1056.        * Note if >= point's X; if so, the ray hits it.
  1057.        * The division operation is avoided for the ">=" test by checking
  1058.        * the sign of the first vertex wrto the test point; idea inspired
  1059.        * by Joseph Samosky's and Mark Haigh-Hutchinson's different
  1060.        * polygon inclusion tests.
  1061.        */
  1062.  
  1063.       if (((vtx1[Y]-ty) * (vtx0[X]-vtx1[X]) >= (vtx1[X]-tx) * (vtx0[Y]-vtx1[Y])) == yflag1)
  1064.       {
  1065.         inside_flag = !inside_flag;
  1066.       }
  1067.     }
  1068.  
  1069.     /* Move to the next pair of vertices, retaining info as possible. */
  1070.  
  1071.     if ((i < Number-2) && (vtx1[X] == first[X]) && (vtx1[Y] == first[Y]))
  1072.     {
  1073.       vtx0 = &Points[++i][X];
  1074.       vtx1 = &Points[++i][X];
  1075.  
  1076.       yflag0 = (vtx0[Y] >= ty);
  1077.  
  1078.       first = vtx0;
  1079.     }
  1080.     else
  1081.     {
  1082.       vtx0 = vtx1;
  1083.       vtx1 = &Points[++i][X];
  1084.  
  1085.       yflag0 = yflag1;
  1086.     }
  1087.   }
  1088.  
  1089.   return(inside_flag);
  1090. }
  1091.  
  1092.